﻿using System;
using System.Collections.Generic;

namespace UnityModule
{
    internal sealed class ReferencePool
    {
        private readonly Queue<IReference> m_References;
        public int MaxCountLimit = 300;
#if UNITY_EDITOR
        private const int WARNING_COUNT = 200;
#endif
        public ReferencePoolInfo PoolInfo
        {
            get;
            private set;
        }

        public ReferencePool(Type referenceType)
        {
            m_References = new Queue<IReference>();
            PoolInfo = new ReferencePoolInfo();
            PoolInfo.TypeFullName = referenceType.FullName;
            PoolInfo.ReferenceType = referenceType;
        }

        public T Get<T>(Func<IReference> createFunc) where T : class, IReference
        {
#if UNITY_EDITOR
            if (PoolInfo.UsingReferenceCount > WARNING_COUNT || m_References.Count > WARNING_COUNT)
            {
                P.E($"{PoolInfo.ReferenceType}:TypeFullName={PoolInfo.TypeFullName} = 警告: 对像池数量异常!{WARNING_COUNT},正在使用数量={PoolInfo.UsingReferenceCount}空闲数量={m_References.Count}");
            }
#endif

            //  lock (m_References)
            {
                if (m_References.Count > 0)
                {
#if UNITY_EDITOR
                    PoolInfo.UsingReferenceCount++;
                    PoolInfo.UnusedReferenceCount--;
#endif
                    return (T)m_References.Dequeue();
                }
            }
            if (null != createFunc)
            {
#if UNITY_EDITOR
                PoolInfo.UsingReferenceCount++;
#endif
                return createFunc() as T;
            }
            else
                return null;
        }


        public T Get<T>() where T : class, IReference, new()
        {
#if UNITY_EDITOR
            if (PoolInfo.UsingReferenceCount > WARNING_COUNT || m_References.Count > WARNING_COUNT) {
                P.E($"{PoolInfo.ReferenceType}:TypeFullName={PoolInfo.TypeFullName} = 警告: 对像池数量异常!{WARNING_COUNT},正在使用数量={PoolInfo.UsingReferenceCount}空闲数量={m_References.Count}");
            }
#endif

            //   lock (m_References)
            {
#if UNITY_EDITOR
                PoolInfo.UsingReferenceCount++;
#endif

                if (m_References.Count > 0)
                {
#if UNITY_EDITOR
                    PoolInfo.UnusedReferenceCount--;
#endif
                    return (T)m_References.Dequeue();
                }
            }
            return new T();
        }


        public void Release(IReference reference)
        {
#if UNITY_EDITOR
            if (PoolInfo.UsingReferenceCount > WARNING_COUNT || m_References.Count > WARNING_COUNT) {
                P.E($"{PoolInfo.ReferenceType}:TypeFullName={PoolInfo.TypeFullName} = 警告: 对像池数量异常!{WARNING_COUNT},正在使用数量={PoolInfo.UsingReferenceCount}空闲数量={m_References.Count}");
            }
#endif

            reference.Clear();
          //  lock (m_References)
            {
#if UNITY_EDITOR
                if (m_References.Contains(reference))
                {
                    P.E(string.Format("reference对像重复Release : {0}", reference.GetType()));
                }
                PoolInfo.UsingReferenceCount--;
                PoolInfo.UnusedReferenceCount++;
#endif
                if (m_References.Count >= MaxCountLimit) {
                    if (PoolInfo.IsNeedDisposeType) {
                        INeedDestroy item = reference as INeedDestroy;
                        item.ToDestroy();
                    }
                } else {
                    m_References.Enqueue(reference);
                }
            }
        }

        public void Add<T>(int count) where T : class, IReference, new()
        {

           // lock (m_References)
            {
#if UNITY_EDITOR
                PoolInfo.UnusedReferenceCount += count;
#endif
                while (count-- > 0)
                {
                    m_References.Enqueue(new T());
                }
            }
        }

        public void Add(int count)
        {
          //  lock (m_References)
            {
#if UNITY_EDITOR
                PoolInfo.UnusedReferenceCount += count;
#endif
                while (count-- > 0)
                {
                    m_References.Enqueue((IReference)Activator.CreateInstance(PoolInfo.ReferenceType));
                }
            }
        }

        public void Remove(int count)
        {
         //   lock (m_References)
            {
                if (count > m_References.Count)
                {
                    count = m_References.Count;
                }
#if UNITY_EDITOR
                PoolInfo.UnusedReferenceCount -= count;
#endif
                if (PoolInfo.IsNeedDisposeType)
                {
                    while (count-- > 0)
                    {
                        INeedDestroy item = m_References.Dequeue() as INeedDestroy;
                        item.ToDestroy();
                    }
                }
                else
                {
                    while (count-- > 0)
                    {
                        m_References.Dequeue();
                    }
                }
            }
        }

        /// <summary>
        /// 清除当前没有引用的
        /// </summary>
        public void RemoveAll()
        {
         //   lock (m_References)
            {
                if (PoolInfo.IsNeedDisposeType)
                {
                    Remove(m_References.Count);
                }
                else
                {
#if UNITY_EDITOR
                    PoolInfo.UnusedReferenceCount = 0;
#endif
                    m_References.Clear();
                }
            }
        }
    }
}
